in the meantime, having changed the Controllers protocol, I am in
trouble. This is partly because of NeXT's implementation of
"conformsTo:" and partly because of the more fundamental versioning
question. NeXT only checks that "Controllers" is in the protocol list
for "someController." Nothing at all is to say that "someController"
has the same concept of what the "Controllers" protocol *is* as I do.
Whoever wrote "someController" might have ignored the compiler
warnings and may in fact not have implemented *any* of the methods.
This could be fixed by having a more robust strictConformsTo: method
which would also verify "respondsTo:" status on all the methods in the
protocol. I still have a problem, however, if the semantics of the
protocol have changed and I'd like to know what version of
"Controllers" "someController" thinks it is responding to.
So, I think it is at least clear that there are "features" in the
current implementation. There are other ramifications as well, but I
leave them to the floor...
Andrew Athan
Date: Thu, 10 Sep 1992 15:12:40 -0700
From: Bruce Nilo <bruce@ictv.com>
To: gnu-objc@prep.ai.mit.edu
Subject: Re: Your mission, should you choose to accept it. . .
I think that NeXT's use of objective C should be just one factor in
guiding the GNU objective C project. The fact of the matter is that
NeXT's implementation of objective C can be improved upon and
interface compatibility can be more or less maintained. Here are some
things which I think can and should be improved.
PROTOCOL IMPROVEMENT: Previous postings have referred to NeXT
protocols as lacking in certain respects. Part of the problem is in
specifying exactly what problem they are suppose to solve. I do not
think that distributed objects was the primary reason for their
introduction. Seperating interface from implementation has been a
topic in OOP for a long time. My personal opinion is that two
compelling reasons for protocols is better compile time error
reporting, and clearer more self documenting code. Runtime support,
although useful, seems less of raison d'etre.
[moved ERROR HANDLING]
[moved BETTER RUNTIME SUPPORT FOR MULTI-THREADED PROGRAMS]
[moved GENERAL DATA STRUCTURES]
- Bruce D. Nilo
VP Software Systems
ICTV
From: Steve_Naroff@next.com (Steve Naroff)
Date: Fri, 11 Sep 92 12:14:25 -0700
To: gnu-objc@prep.ai.mit.edu
Subject: NeXT implementation of protocols
I'm glad to see some folks are reading the documentation (it saves time)! Just to summarize, protocols definitely serve two purposes, they are:
(1) As a language feature, protocols provide a better way to declare pure, abstract data types (independent of the class hierarchy). We feel this encourages the reuse of design and provides better type checking (without compromising the flexibility of "id").
(2) As for distributed objects, protocols provide the runtime support to improve the efficiency and expressiveness of doing distributed programming, where the "class" may reside in another application. Note that we do not "force" you to use protocols, it is just slower and less descriptive than if you do.
Here are some brief comments on the headbutts that have been mentioned:
(1) Integration with class methods. The example given was was flawed, however...here is a slightly modified version:
id <Controllers> buggy = [SomeControllerClass new];
id <Controllers> notBuggy = [SomeControllerClass class];
[notBuggy someClassMethod]; // but produces bogus warning
[buggy someClassMethod]; // this was a flawed example
}
The "real bug" is there is no way to declare "a class object for type SomeControllerClass", hence the bogus warning. This is where Objective-C's heritage of totally anonymous objects shines through! We were aware of this, it isn't hard to fix.
(2) Integration with categories. Category can adopt protocols just like classes. Here is a simple example that illustrates two possible organizations of a class.
I'm not sure this solves your problem, however I thought you might be interested in this capability. The suggestion that the compiler treat language elements (like classes/categories) differently, based on whether or not they happen to be in the same ".m" is flawed.
(3) Protocol versioning. We are well aware of this problem and didn't have time to come up with a solution we felt comfortable with. The problem is we don't do any type checking across module boundaries (either at linktime or runtime). Each ".o" module that references a protocol (via @protocol) gets a copy of the protocol object (the linker does not unique them) used by the runtime system for that module. Since protocols are "abstract", they have no obvious "home" (i.e. place to generate them, like there is for classes)...as a result, attaching a version # is tricky. I'm glad there are other folks thinking about solutions to this problem.
In summary, I am glad to see support for improving the NeXT implementation of protocols and hope some of this info helps. We are using protocols quite extensively within NeXT and have some ideas for future enhancements (I will keep you posted).
bye, snaroff.
Date: Fri, 11 Sep 92 15:28:07 -0400
From: athan@object.com (Andrew Athan)
To: gnu-objc@prep.ai.mit.edu
Subject: Re: NeXT implementation of protocols
In response to my having complained about spurious compiler warnings when some protocol is implemented in whole in one .m file, but the various methods in the protocol are actually split between multiple categories in that .m, Steve_Naroff@NeXT.com writes:
>(2) Integration with categories. Category can adopt protocols just like classes. Here is a
>simple example that illustrates two possible organizations of a class.
and gives an example illustrating the ability to declare that a *category* responds to some protocol:
Stated as I have in the first sentence of this email, Steve's example does not solve the problem. It is useful when the protocol you are trying to implement happens to be "decomposable." It has the disadvantage that "AnotherWayToOrganize" no longer responds to the <Archiving> protocol, only to the <Read> and to the <Write> protocols. I am under the impression that asking conformsTo:@protocol(Archiving) to the object will then yield NO (am I right Steve?)
I think the compiler should not issue warnings regarding non-conformance to protocols until the entire .m file has been processed.
Andrew Athan
From: Steve_Naroff@next.com (Steve Naroff)
Date: Sun, 13 Sep 92 08:28:35 -0700
To: athan@object.com (Andrew Athan)
Subject: Re: NeXT implementation of protocols
Cc: gnu-objc@prep.ai.mit.edu
> I am under the impression that asking conformsTo:@protocol(Archiving) to the object will then yield NO (am I right Steve?)
You are right...my original email said "I'm not sure this solves your problem, however I thought you might be interested in this capability." I guess you weren't.
> I think the compiler should not issue warnings regarding non-conformance to protocols until the entire .m file has been processed.
I'm not sure I understand your suggestion. In general, I don't like "file boundaries" to effect language semantics. The unit of modularity in Objective-C is the class, category, protocol, etc...what files these entities reside in is irrelevant to the compiler. Context dependencies make it hard to reorganize various aspects of your program. I'm not saying your desire to implement a protocol across class/category boundaries is superfluous, I just don't like relying on file boundaries to implement it.
snaroff.
Date: Mon, 14 Sep 92 10:35:38 CDT
From: billb@jupiter.fnbc.com
To: gnu-objc@prep.ai.mit.edu
Subject: Protocols, Reflection
At first blush the idea of versioning protocols seemed appropriate. Now, after thinking more about protocols I believe that perhaps I would like a better implementation, to wit: Why are protocols checked by name and not by _value_? This is yet another barrier between us and code reuse. When I write a class I cannot possibly imagine all of the protocols that that class responds to (combination of all methods it implements), yet that class _does_ respond to any protocol which specifies some subset of that class' methods. Please, someone, correct me if I am wrong about the way that protocol conformance is determined at runtime. Protocols should _eliminate_ the version dependence of our code! Protocols should be interfaces. If an object has the same interface, then I don't care what version it is. Of course this may be naive of me.
Also, while I have your ear, wouldn't it be nice to have some more powerful reflective facilities in the language. Maybe I just need to dig deeper into Obj-C++, but I haven't seen the kind of facilities that I really need. If such changes are _off_limits_ for this projects then just stop reading _now_.
An example of a useful reflective capability would be the ability to override an Object method that would automatically get invoked every time any method is entered; I would also like a similar method for method exit. I would like to be able to override these methods for a given class, and additionally for particular instances of a class.
see:
[Graube 89] N. Graube, "Metaclass Compatibility" OOPSLA '89 Conference Proceedings, Special Issue of Sigplan Notices, Vol. 24 No. 10, October 1989.
[Ferber 89] J. Ferber, "Computational Reflection in Class based Object Oriented Languages" OOPSLA '89 Conference Proceedings, Special Issue of Sigplan Notices, Vol. 24 No. 10, October 1989.
[Foote & Johnson 89] B. Foote and R.E. Johnson, "Reflective Facilities in Smalltalk-80" OOPSLA '89 Conference Proceedings, Special Issue of Sigplan Notices, Vol. 24 No. 10, October 1989.
(gimme a break -- I _do_ _to_ have more than one book!)
That's all.
Bill
Date: Tue, 15 Sep 92 11:07:21 CDT
From: billb@jupiter.fnbc.com
To: gnu-objc@prep.ai.mit.edu
Subject: Re: Protocols, Reflection (forgive my rambling)
> billb@fnbc.com writes:
> > <<stuff omitted>>
> > Please, someone, correct me if I am wrong about the way
> > that protocol conformance is determined at runtime.
> > Protocols should _eliminate_ the version dependence of
> > our code! Protocols should be interfaces. If an object
> > has the same interface, then I don't care what version it
> > is. Of course this may be naive of me.
> > <<stuff omitted>>
>
> athan@object.com (Andrew Athan) writes:
> The question is, what assumption do we want to make? If I
> respond to someMethod, shall I assume that its semantics
> will always remain the same? If so, then what you say is
> true. However, if between version1 of someProtocol and
> version2, the method setStringValue: starting doing
> something differently (e.g., updating a database as
> well as the object itself) then I could conceivably need
> to know that version I'm talking to.
>
> An additional point is: Is what I've described a question
> of protocol or object versioning? Does anyone have
> arguments pro/con this?
I see your point. I didn't really understand what was bugging me until I read your response. So, do we add semantic information to protocols?!? No, because that puts us right back where we started -- if we could express the semantics in the protocol then we would already have an implementation.
Your point brings up the following problem: we are talking about two distinct entities here. One is already implemented by the Obj-C protocol. The other is a semantic specification (currently in the implementors head) of the semantics of those methods. Version numbers on protocols really have nothing to do w/ Obj-C protocols, but everything to do w/ identifying some (currently undocumented) semantic description of objects. It would be just as valid to change the protocol name each time the protocol was rev'd (add a vers count to the end of the name if you like) as it would be to have a seperate version number. Its all just a naming problem -- just like so many of our problems.
[[billb putPropellorOnHead] mountSoapbox]
IMHO we should do away w/ our one-dimensional programming paradigms in which we use names to refer to _things_, and instead actually specify to those _things_ directly, as we program. There should be no `symbol table' in a compiler. I should be able to annotate (or not) any entity in my program. How long am I going to have to suffer the lowest common denominator (vi) for program entry. We all have GUI's now don't we?
I want to strongly second the motion that Kim Christensen has suggested! The particular problem solved by this solution is not as important as the fact that we need the ability to override objc_msgSend(). I was thinking of sending an almost identical suggestion myself, but Kim has saved me the trouble (as well as verified my thinking).
We have encountered many problems here at WilTel which could have been easily handled if we had the ability to "override" the objc_msgSend() function. For example, we have an approach to persistant object storage which is far more complicated (and inefficient) than it need be if we had the ability to augment obj_msgSend(). Kim's suggestion is an excellent one which can handle numerous problems. Of course, there may be hidden problems which I'm not seeing, but something like this is sorely needed.
Charles Lloyd.
ps: I hope this discussion is considered to be germane to the project. This gnu effort has an opportunity to correct some of the deficiencies in the NeXT implementation and I think its wise to get these ideas heard early in this forum.
Date: Tue, 15 Sep 92 08:10:31 +0100
From: Kim Harding Christensen <uunet!dannug.dk!khc>
To: gnu-objc@prep.ai.mit.edu
Subject: Re:Protocols, Reflection
<stuff deleted>
We could do all these things (and a lot more) if the messenger function is implemented as a pointer to a function:
id objc_msgSend(id self, SEL theSelector, ...)
{
....
}
theMessenger = objc_msgSend;
<stuff deleted>
Date: Tue, 15 Sep 92 08:10:31 +0100
From: Kim Harding Christensen <khc@dannug.dk>
To: gnu-objc@prep.ai.mit.edu
Subject: Re:Protocols, Reflection
Bill writes:
> .... Also, while I have your ear, wouldn't it be nice to have
> some more powerful reflective facilities in the
> language. Maybe I just need to dig deeper into Obj-C++,
> but I haven't seen the kind of facilities that I really
> need. If such changes are _off_limits_ for this projects
> then just stop reading _now_.
> An example of a useful
> reflective capability would be the ability to override
> an Object method that would automatically get invoked
> every time any method is entered; I would also like a
> similar method for method exit. I would like to be able to
> override these methods for a given class, and
> additionally for particular instances of a class.
>
We could do all these things (and a lot more) if the messenger function is implemented as a pointer to a function:
id objc_msgSend(id self, SEL theSelector, ...)
{
....
}
theMessenger = objc_msgSend;
To implement pre- and post-condition we could write something like:
id preAndPostMessenger(id self, SEL theSelector, ...)